package cn.iocoder.yudao.module.lowcode.core.script;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import groovy.json.JsonBuilder;
import groovy.json.JsonSlurper;
import groovy.sql.Sql;
import groovy.sql.GroovyRowResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.regex.Pattern;

/**
 * Groovy 脚本助手类
 * 
 * 为Groovy脚本提供常用的工具方法和功能
 * 
 * @author 芋道源码
 */
@Slf4j
@Component
public class GroovyScriptHelper {

    /**
     * JSON 处理工具
     */
    public static class JsonHelper {
        private static final JsonSlurper jsonSlurper = new JsonSlurper();
        
        /**
         * 解析JSON字符串
         */
        public static Object parseJson(String jsonText) {
            return jsonSlurper.parseText(jsonText);
        }
        
        /**
         * 对象转JSON字符串
         */
        public static String toJson(Object object) {
            JsonBuilder builder = new JsonBuilder(object);
            return builder.toString();
        }
        
        /**
         * 对象转格式化JSON字符串
         */
        public static String toPrettyJson(Object object) {
            JsonBuilder builder = new JsonBuilder(object);
            return builder.toPrettyString();
        }
        
        /**
         * 使用YuDao的JSON工具
         */
        public static String toYudaoJson(Object object) {
            return JsonUtils.toJsonString(object);
        }
        
        /**
         * 使用YuDao的JSON工具解析
         */
        public static <T> T parseYudaoJson(String jsonText, Class<T> clazz) {
            return JsonUtils.parseObject(jsonText, clazz);
        }
    }

    /**
     * 数学计算工具
     */
    public static class MathHelper {
        
        /**
         * 精确的加法运算
         */
        public static BigDecimal add(Object... numbers) {
            BigDecimal result = BigDecimal.ZERO;
            for (Object number : numbers) {
                result = result.add(new BigDecimal(number.toString()));
            }
            return result;
        }
        
        /**
         * 精确的减法运算
         */
        public static BigDecimal subtract(Object a, Object b) {
            return new BigDecimal(a.toString()).subtract(new BigDecimal(b.toString()));
        }
        
        /**
         * 精确的乘法运算
         */
        public static BigDecimal multiply(Object a, Object b) {
            return new BigDecimal(a.toString()).multiply(new BigDecimal(b.toString()));
        }
        
        /**
         * 精确的除法运算
         */
        public static BigDecimal divide(Object a, Object b, int scale) {
            return new BigDecimal(a.toString()).divide(new BigDecimal(b.toString()), scale, RoundingMode.HALF_UP);
        }
        
        /**
         * 生成随机数
         */
        public static int randomInt(int min, int max) {
            return ThreadLocalRandom.current().nextInt(min, max + 1);
        }
        
        /**
         * 生成随机小数
         */
        public static double randomDouble(double min, double max) {
            return ThreadLocalRandom.current().nextDouble(min, max);
        }
    }

    /**
     * 字符串处理工具
     */
    public static class StringHelper {
        
        /**
         * 判断字符串是否为空
         */
        public static boolean isEmpty(String str) {
            return str == null || str.trim().isEmpty();
        }
        
        /**
         * 判断字符串是否非空
         */
        public static boolean isNotEmpty(String str) {
            return !isEmpty(str);
        }
        
        /**
         * 字符串格式化
         */
        public static String format(String template, Object... args) {
            return String.format(template, args);
        }
        
        /**
         * 正则表达式匹配
         */
        public static boolean matches(String str, String regex) {
            return Pattern.matches(regex, str);
        }
        
        /**
         * 正则表达式替换
         */
        public static String replaceAll(String str, String regex, String replacement) {
            return str.replaceAll(regex, replacement);
        }
        
        /**
         * 生成UUID
         */
        public static String uuid() {
            return UUID.randomUUID().toString();
        }
        
        /**
         * 生成短UUID (去掉横线)
         */
        public static String shortUuid() {
            return UUID.randomUUID().toString().replace("-", "");
        }
    }

    /**
     * 日期时间处理工具
     */
    public static class DateHelper {
        
        /**
         * 获取当前时间
         */
        public static LocalDateTime now() {
            return LocalDateTime.now();
        }
        
        /**
         * 格式化日期时间
         */
        public static String format(LocalDateTime dateTime, String pattern) {
            return DateTimeFormatter.ofPattern(pattern).format(dateTime);
        }
        
        /**
         * 解析日期时间
         */
        public static LocalDateTime parse(String dateTimeStr, String pattern) {
            return LocalDateTime.parse(dateTimeStr, DateTimeFormatter.ofPattern(pattern));
        }
        
        /**
         * 获取今天开始时间
         */
        public static LocalDateTime beginOfDay() {
            return LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
        }
        
        /**
         * 获取今天结束时间
         */
        public static LocalDateTime endOfDay() {
            return LocalDateTimeUtil.endOfDay(LocalDateTime.now());
        }
        
        /**
         * 获取时间戳
         */
        public static long timestamp() {
            return System.currentTimeMillis();
        }
        
        /**
         * 格式化为常用格式
         */
        public static String formatNow() {
            return format(now(), "yyyy-MM-dd HH:mm:ss");
        }
        
        /**
         * 格式化为日期格式
         */
        public static String formatDate() {
            return format(now(), "yyyy-MM-dd");
        }
    }

    /**
     * 集合处理工具
     */
    public static class CollectionHelper {
        
        /**
         * 判断集合是否为空
         */
        public static boolean isEmpty(Collection<?> collection) {
            return collection == null || collection.isEmpty();
        }
        
        /**
         * 判断集合是否非空
         */
        public static boolean isNotEmpty(Collection<?> collection) {
            return !isEmpty(collection);
        }
        
        /**
         * 创建ArrayList
         */
        public static <T> List<T> newList(T... elements) {
            return new ArrayList<>(Arrays.asList(elements));
        }
        
        /**
         * 创建HashMap
         */
        public static <K, V> Map<K, V> newMap() {
            return new HashMap<>();
        }
        
        /**
         * 创建HashSet
         */
        public static <T> Set<T> newSet(T... elements) {
            return new HashSet<>(Arrays.asList(elements));
        }
        
        /**
         * 列表去重
         */
        public static <T> List<T> distinct(List<T> list) {
            return new ArrayList<>(new LinkedHashSet<>(list));
        }
        
        /**
         * 列表分页
         */
        public static <T> List<T> page(List<T> list, int pageNum, int pageSize) {
            int start = (pageNum - 1) * pageSize;
            int end = Math.min(start + pageSize, list.size());
            if (start >= list.size()) {
                return new ArrayList<>();
            }
            return list.subList(start, end);
        }
    }

    /**
     * HTTP请求工具
     */
    public static class HttpHelper {
        
        /**
         * 构建查询参数
         */
        public static String buildQueryString(Map<String, Object> params) {
            if (params == null || params.isEmpty()) {
                return "";
            }
            
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                if (sb.length() > 0) {
                    sb.append("&");
                }
                sb.append(entry.getKey()).append("=").append(entry.getValue());
            }
            return sb.toString();
        }
        
        /**
         * 构建完整URL
         */
        public static String buildUrl(String baseUrl, Map<String, Object> params) {
            String queryString = buildQueryString(params);
            if (queryString.isEmpty()) {
                return baseUrl;
            }
            
            String separator = baseUrl.contains("?") ? "&" : "?";
            return baseUrl + separator + queryString;
        }
        
        /**
         * 执行GET请求（安全版本）
         */
        public static Map<String, Object> get(String url) {
            return get(url, null);
        }
        
        /**
         * 执行GET请求（安全版本）
         */
        public static Map<String, Object> get(String url, Map<String, String> headers) {
            try {
                java.net.URL urlObj = new java.net.URL(url);
                java.net.HttpURLConnection conn = (java.net.HttpURLConnection) urlObj.openConnection();
                
                // 设置请求方法
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(5000);
                conn.setReadTimeout(10000);
                
                // 设置请求头
                if (headers != null) {
                    for (Map.Entry<String, String> header : headers.entrySet()) {
                        conn.setRequestProperty(header.getKey(), header.getValue());
                    }
                }
                
                // 执行请求
                int responseCode = conn.getResponseCode();
                String responseText;
                
                if (responseCode >= 200 && responseCode < 300) {
                    responseText = readInputStream(conn.getInputStream());
                } else {
                    responseText = readInputStream(conn.getErrorStream());
                }
                
                Map<String, Object> result = new HashMap<>();
                result.put("status", responseCode);
                result.put("body", responseText);
                result.put("headers", getResponseHeaders(conn));
                return result;
                
            } catch (Exception e) {
                log.error("HTTP GET请求失败: {}", url, e);
                Map<String, Object> result = new HashMap<>();
                result.put("status", -1);
                result.put("error", e.getMessage());
                result.put("body", "");
                return result;
            }
        }
        
        /**
         * 执行POST请求（安全版本）
         */
        public static Map<String, Object> post(String url, String body) {
            return post(url, body, "application/json", null);
        }
        
        /**
         * 执行POST请求（安全版本）
         */
        public static Map<String, Object> post(String url, String body, String contentType, Map<String, String> headers) {
            try {
                java.net.URL urlObj = new java.net.URL(url);
                java.net.HttpURLConnection conn = (java.net.HttpURLConnection) urlObj.openConnection();
                
                // 设置请求方法
                conn.setRequestMethod("POST");
                conn.setConnectTimeout(5000);
                conn.setReadTimeout(10000);
                conn.setDoOutput(true);
                
                // 设置内容类型
                if (contentType != null) {
                    conn.setRequestProperty("Content-Type", contentType);
                }
                
                // 设置请求头
                if (headers != null) {
                    for (Map.Entry<String, String> header : headers.entrySet()) {
                        conn.setRequestProperty(header.getKey(), header.getValue());
                    }
                }
                
                // 发送请求体
                if (body != null && !body.isEmpty()) {
                    try (java.io.OutputStream os = conn.getOutputStream()) {
                        byte[] input = body.getBytes("UTF-8");
                        os.write(input, 0, input.length);
                    }
                }
                
                // 执行请求
                int responseCode = conn.getResponseCode();
                String responseText;
                
                if (responseCode >= 200 && responseCode < 300) {
                    responseText = readInputStream(conn.getInputStream());
                } else {
                    responseText = readInputStream(conn.getErrorStream());
                }
                
                Map<String, Object> result = new HashMap<>();
                result.put("status", responseCode);
                result.put("body", responseText);
                result.put("headers", getResponseHeaders(conn));
                return result;
                
            } catch (Exception e) {
                log.error("HTTP POST请求失败: {}", url, e);
                Map<String, Object> result = new HashMap<>();
                result.put("status", -1);
                result.put("error", e.getMessage());
                result.put("body", "");
                return result;
            }
        }
        
        private static String readInputStream(java.io.InputStream is) {
            if (is == null) return "";
            
            try (java.util.Scanner scanner = new java.util.Scanner(is, "UTF-8")) {
                return scanner.useDelimiter("\\A").hasNext() ? scanner.next() : "";
            }
        }
        
        private static Map<String, String> getResponseHeaders(java.net.HttpURLConnection conn) {
            Map<String, String> headers = new HashMap<>();
            for (Map.Entry<String, java.util.List<String>> entry : conn.getHeaderFields().entrySet()) {
                if (entry.getKey() != null && entry.getValue() != null && !entry.getValue().isEmpty()) {
                    headers.put(entry.getKey(), entry.getValue().get(0));
                }
            }
            return headers;
        }
    }

    /**
     * 数据库操作工具
     */
    public static class DatabaseHelper {
        
        /**
         * 创建SQL操作实例
         */
        public static Sql createSql(DataSource dataSource) {
            try {
                return new Sql(dataSource);
            } catch (Exception e) {
                log.error("创建SQL实例失败", e);
                throw new RuntimeException("创建SQL实例失败: " + e.getMessage(), e);
            }
        }
        
        /**
         * 执行查询并返回结果列表
         */
        @SuppressWarnings("unchecked")
        public static List<Map<String, Object>> query(DataSource dataSource, String sql, Object... params) {
            try (Sql sqlInstance = createSql(dataSource)) {
                List<?> rows;
                if (params != null && params.length > 0) {
                    rows = sqlInstance.rows(sql, Arrays.asList(params));
                } else {
                    rows = sqlInstance.rows(sql);
                }
                
                // 转换为标准的Map列表
                List<Map<String, Object>> results = new ArrayList<>();
                for (Object rowObj : rows) {
                    if (rowObj instanceof GroovyRowResult) {
                        GroovyRowResult row = (GroovyRowResult) rowObj;
                        Map<String, Object> map = new HashMap<>();
                        for (Object key : row.keySet()) {
                            map.put(String.valueOf(key), row.get(key));
                        }
                        results.add(map);
                    }
                }
                return results;
            } catch (Exception e) {
                log.error("执行SQL查询失败: {}", sql, e);
                throw new RuntimeException("执行SQL查询失败: " + e.getMessage(), e);
            }
        }
        
        /**
         * 执行更新操作
         */
        public static int update(DataSource dataSource, String sql, Object... params) {
            try (Sql sqlInstance = createSql(dataSource)) {
                if (params != null && params.length > 0) {
                    return sqlInstance.executeUpdate(sql, Arrays.asList(params));
                } else {
                    return sqlInstance.executeUpdate(sql);
                }
            } catch (Exception e) {
                log.error("执行SQL更新失败: {}", sql, e);
                throw new RuntimeException("执行SQL更新失败: " + e.getMessage(), e);
            }
        }
    }

    /**
     * 日志工具
     */
    public static class LogHelper {
        
        public static void info(String message, Object... args) {
            log.info(message, args);
        }
        
        public static void warn(String message, Object... args) {
            log.warn(message, args);
        }
        
        public static void error(String message, Object... args) {
            log.error(message, args);
        }
        
        public static void debug(String message, Object... args) {
            log.debug(message, args);
        }
    }

    /**
     * 脚本执行上下文工具
     */
    public static class ContextHelper {
        
        /**
         * 获取上下文参数
         */
        public static Object getParam(Map<String, Object> context, String key) {
            return context.get(key);
        }
        
        /**
         * 获取上下文参数，如果不存在返回默认值
         */
        public static Object getParam(Map<String, Object> context, String key, Object defaultValue) {
            return context.getOrDefault(key, defaultValue);
        }
        
        /**
         * 设置上下文参数
         */
        public static void setParam(Map<String, Object> context, String key, Object value) {
            context.put(key, value);
        }
        
        /**
         * 构建响应结果
         */
        public static Map<String, Object> buildResult(Object data) {
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("data", data);
            result.put("timestamp", System.currentTimeMillis());
            return result;
        }
        
        /**
         * 构建错误响应
         */
        public static Map<String, Object> buildError(String message) {
            Map<String, Object> result = new HashMap<>();
            result.put("success", false);
            result.put("message", message);
            result.put("timestamp", System.currentTimeMillis());
            return result;
        }
    }
}